import { io } from "socket.io-client"
import WebrtcConnection from './WebrtcConnection'

const socket = io("https://localhost:3000")

socket.on("connect", () => {
  console.log("Connected to server")

  socket.on("message", (payload) => {
    const {type, data} = payload
    switch(type) {
      case "joinRoom":
        receiveJoinRoom(data)
        break;
      case "offer":
        receiveOffer(data)
        break;
      case "answer":
        receiveAnswer(data)
        break;
      case "candidate":
        receiveCandidate(data)
        break;
      default:
    }
  })
})

const peers = new Map()
const startBtn = document.getElementById("start")
const toggleBtn = document.getElementById("stop")
const shareBtn = document.getElementById("share")
const localVideo = document.getElementById("localVideo")
let roomId;
let userId;
let localStream;
let playing = false;

startBtn.addEventListener("click", () => handleInit("camera"))

shareBtn.addEventListener("click", () => handleInit("screen"))

toggleBtn.addEventListener("click", () => {
  playing = !playing
  for (const connection of peers.values()) {
    connection.toggleVideoTrack(localStream, playing)
  }
})

async function handleInit(mediaType){
  roomId = document.getElementById("roomId").value
  userId = document.getElementById("userId").value
  if (!roomId || !userId) {
    alert("请输入房间号和用户ID")
    return
  }

  // 清空已存在的流
  if (localStream) {
    localStream.getTracks().forEach((track) => track.stop())
  }
  // 获取本地流
  localStream = await createlocalStream(mediaType)
  // 将流注入到本地视频标签中
  localVideo.srcObject = localStream
  // 如果连接已经建立，则也修改 senders 的视频轨道
  if (peers.size > 0) {
    for (const connection of peers.values()) {
      connection.changeSendersVideoTrack(localStream)
    }
  }
  console.log("流发生了改变")
  socket.emit("joinRoom", { roomId, userId })
}

// 用户进入房间时的通知
// A
async function receiveJoinRoom(reply){
  const { roomId, userId: newUserId } = reply

  // 创建 RTC 实例连接
  const connection = getPeerConnection(newUserId)

  // 将本地流加入到 RTC 实例中
  connection.addTrack(localStream)

  // 创建本地 offer，并设置为本地描述
  const offer = await connection.createAndSetLocalOffer()

  // 发送本地 offer
  socket.emit("offer", { offer, roomId, userId, newUserId })
  console.log(userId, "创建Offer给", newUserId)
}

// B
async function receiveOffer(reply){
  const { offer, userId: fromUserId } = reply

  // 获取 RTC 实例
  const connection = getPeerConnection(fromUserId)

  // 将本地流加入到 RTC 实例中
  connection.addTrack(localStream)

  // 将远程 offer 设为存入到 RTC 中
  connection.setRemoteDescription(offer)
  console.log("remote offer", fromUserId, offer)

  // 创建本地 answer、设为本地 answer、发送本地 answer
  const answer = await connection.createAndSetLocalAnswer()

  socket.emit("answer", { answer, roomId, userId, fromUserId })

  
  console.log(userId, "收到 Offer, 创建Answer给", fromUserId)

}

// A
function receiveAnswer(reply){
  const { answer, userId: newUserId} = reply
  const connection = getPeerConnection(newUserId)
  connection.setRemoteDescription(answer)
  console.log(userId, "收到 Answer， 给peerId 为", newUserId, "设置远端描述")
}

// A/B
function receiveCandidate(reply){
  const { candidate, userId: fromUserId } = reply
  const connection = getPeerConnection(fromUserId)
  connection.setRemoteCandidate(candidate)

}

// 从媒体设备获取音视频流
async function createlocalStream(mediaType){
  let localStream;
  try {
    if (mediaType === "camera") {
      localStream = await navigator.mediaDevices.getUserMedia(
        {
          video: true,
          audio: true
        }
      )
    } else {
      localStream = await navigator.mediaDevices.getDisplayMedia(
        {
          video: true,
          audio: true
        }
      )
    }
    return localStream
  } catch (err) {
    // 由于我的电脑没有两个摄像头，因此先用共享桌面作为媒体流替代
    localStream = await navigator.mediaDevices.getDisplayMedia(
      {
        video: true,
        audio: true
      }
    )
    return localStream
  }
}

function createRemoteVideoArea(userId, remoteStream){
  const container = document.querySelector(".video-container")

  if (!document.getElementById(userId)) {
    const videoHTML = `
      <div class="remoteArea">
          <video id=${userId} playsinline autoplay></video>
          <h4>远端视频(ID: ${userId})</h4>
        </div>
    `
    container.insertAdjacentHTML("beforeend", videoHTML)

    const videoElement = document.getElementById(userId)
    videoElement.srcObject = remoteStream
  }
}

function getPeerConnection(fromUserId){
  let connection = peers.get(fromUserId)
  if (!connection) { 
    connection = new WebrtcConnection();
    connection.create((candidate) => {
      console.log("媒体协商完成")
      socket.emit("candidate", { candidate, roomId, userId, fromUserId });
    }, (remoteStream) => {
      console.log("P2P连接成功")
      createRemoteVideoArea(fromUserId, remoteStream)
      playing = true;
    });
    peers.set(fromUserId, connection);

    console.log("RTC实例列表", peers)
  }
  
  return connection; 
}